package com.woniuxy.userweb.controller;



import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.woniuxy.core.exception.ParameterValidException;
import com.woniuxy.core.model.Result;
import com.woniuxy.core.util.DateUtil;
import com.woniuxy.core.util.MyJwtUtil;
import com.woniuxy.userdao.model.UserInfo;
import com.woniuxy.userdao.model.UserLoginLog;
import com.woniuxy.usermodel.CoachListUserDto;
import com.woniuxy.usermodel.dto.*;
import com.woniuxy.usermodel.form.*;
import com.woniuxy.userservice.exception.UserInfoException;
import com.woniuxy.userservice.service.UserInfoService;
import com.woniuxy.userservice.service.UserLoginLogService;
import com.woniuxy.util.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author 冉杰
 * @since 2024-01-15
 */
@Api(tags = {"用户资源接口"})
@RestController
@RequestMapping("/userInfo")
public class UserInfoController {
    @Value("${server.port}")
    private int port;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserLoginLogService userLoginLogService;

    /**
     * @param form 接受用户注册的参数列表
     * @return 无
     */
    @ApiOperation("用户注册接口")
    @PostMapping("/register")
    public Result userRegister(@RequestBody @Validated UserRegisterForm form){
        userInfoService.userRegister(form);
        return Result.success("用户注册成功",null);
    }

    /**
     * @param phone 手机号
     * @return
     */
    @ApiOperation("用户注册发送验证码")
    @GetMapping("/registerSendCode")
    public Result userRegisterSendCode(String phone){
        if (ObjectUtils.isEmpty(phone)) throw new ParameterValidException(500,"参数校验错误");
        String regex = "1[3-9]\\d{9}"; // 手机号码的正则表达式
        Matcher matcher = java.util.regex.Pattern.compile(regex).matcher(phone);
        if (!matcher.matches())
            throw new ParameterValidException(500,"手机号格式有误");
        userInfoService.userRegisterSendCode(phone);
        return Result.success("验证码发送成功",null);
    }

    /**
     * @param form 接受用户手机号登录参数
     * @param br 参数校验对象
     * @param resp 该请求的响应
     * @return
     */
    @ApiOperation("用户手机号验证码登录接口")
    @PostMapping("/phoneLogin")
    public Result<UserLoginDto> userPhoneLogin(@RequestBody @Validated UserPhoneLoginForm form,
                                               HttpServletResponse resp, HttpServletRequest req){
        UserLoginDto dto = userInfoService.userCodeLogin(form);
        //签发token
        Map<String, Object> map = new HashMap<>();
        map.put("userId",dto.getUserId());
        //生成短token
        String accessToken = MyJwtUtil.createUserToken(map,240);
        resp.setHeader("token",accessToken);
        //在跨域请求访问时 必须公开该请求头 前端才能获取到
        resp.setHeader("Access-Control-Expose-Headers","token");
        //登录日志
        String ip = req.getRemoteAddr();
        String loginAddr = ip + ":" + port;
        UserLoginLog loginLog = new UserLoginLog();
        loginLog.setLogAddr(loginAddr);
        loginLog.setUserPhone(dto.getUserPhone());
        loginLog.setUserId(dto.getUserId());
        loginLog.setUserAccount(dto.getUserAccount());
        loginLog.setLogTime(DateUtil.dateTimeToString(new Date()));
        userLoginLogService.save(loginLog);
        return Result.success("用户登录成功",dto);
    }

    /**
     *
     * @param phone 手机号
     * @return
     */
    @ApiOperation("用户登录发送验证码")
    @GetMapping("/loginSendCode")
    public Result userLoginSendCode(String phone){
        if (ObjectUtils.isEmpty(phone)) throw new ParameterValidException(500,"参数校验错误");
        String regex = "1[3-9]\\d{9}"; // 手机号码的正则表达式
        Matcher matcher = java.util.regex.Pattern.compile(regex).matcher(phone);
        if (!matcher.matches())
            throw new ParameterValidException(500,"手机号格式有误");
        userInfoService.userLoginSendCode(phone);
        return Result.success("登录验证码发送成功",null);
    }

    /**
     *
     * @param form 账号登录参数对象
     * @param br 参数绑定对象
     * @param resp 响应对象
     * @param req 请求对象
     * @return
     */
    @ApiOperation("用户账号密码登录")
    @PostMapping("/accountLogin")
    public Result<UserLoginDto> userAccountLogin(@RequestBody @Validated UserAccountLoginForm form,
                                                 HttpServletResponse resp, HttpServletRequest req) {
        UserLoginDto dto = userInfoService.userAccountLogin(form);
        //签发token
        Map<String, Object> map = new HashMap<>();
        map.put("userId",dto.getUserId());
        //生成短token
        String accessToken = MyJwtUtil.createUserToken(map,240);
        resp.setHeader("token",accessToken);
        //在跨域请求访问时 必须公开该请求头 前端才能获取到
        resp.setHeader("Access-Control-Expose-Headers","token");
        //登录日志
        String ip = req.getRemoteAddr();
        String loginAddr = ip + ":" + port;
        UserLoginLog loginLog = new UserLoginLog();
        loginLog.setLogAddr(loginAddr);
        loginLog.setUserPhone(dto.getUserPhone());
        loginLog.setUserId(dto.getUserId());
        loginLog.setUserAccount(dto.getUserAccount());
        loginLog.setLogTime(DateUtil.dateTimeToString(new Date()));
        userLoginLogService.save(loginLog);
        return Result.success("用户登录成功",dto);
    }

    /**
     *
     * @param idCardFile 身份证照片
     * @param token 登录token
     * @return
     * @throws IOException
     */
    @ApiOperation("用户身份证实名认证接口")
    @PostMapping("/userOauth")
    public Result<UserOauthDto> userOauth(MultipartFile idCardFile,@RequestHeader String token) throws Exception {
        Integer userId = MyJwtUtil.getUserIdByKey(token, "userId");
        UserOauthDto dto = userInfoService.userOauth(idCardFile,userId);
        return Result.success("实名认证成功",dto);
    }

    /**
     *
     * @param updateFile 头像图片，格式jpg或png
     * @param token 登录认证token
     * @return
     * @throws IOException
     */
    @ApiOperation("修改用户头像")
    @PostMapping("/updateUserAvatar")
    public Result updateUserAvatar(MultipartFile updateFile ,@RequestHeader String token) throws IOException {
        Integer userId = MyJwtUtil.getUserIdByKey(token, "userId");
        userInfoService.updateUserAvatar(updateFile,userId);
        return Result.success("修改头像成功");
    }

    @ApiOperation("用户查看自己的个人信息")
    @GetMapping("/look")
    public Result<UserLookDto> userLook(@RequestHeader String token){
        UserInfo userInfo = userInfoService.getById(MyJwtUtil.getUserIdByKey(token, "userId"));
        UserLookDto dto = BeanUtil.toBean(userInfo,UserLookDto.class);
        return Result.success("用户查看个人信息成功",dto);
    }

    /**
     *
     * @param form 管理端查询用户的条件参数
     * @return 返回的用户信息对象
     */
    @ApiOperation("管理端条件查看用户信息")
    @PostMapping("/adminList.api")
    public Result adminListUsers(@RequestBody AdminListUserForm form){
       PageInfo<AdminListUserDto> pageInfo =  userInfoService.adminListUsers(form);
       return Result.success("查看用户信息成功",pageInfo);
    }

    /**教练端条件查看学员信息
     * @param form 教练端查询学员的条件参数
     * @param token 教练的登录token
     * @return
     */
    @ApiOperation("教练端条件查看学员信息")
    @PostMapping("/coachList.coach")
    public Result<List<CoachListUserDto>> coachListUser(@RequestBody CoachListUserForm form, @RequestHeader String token){
        Integer coachId = MyJwtUtil.getCoachIdByKey(token, "coachId");
        List<CoachListUserDto> dtos = userInfoService.coachListUser(form,coachId);
       return Result.success("查看学员成功",dtos);
    }

    /**
     * 商家端条件查看学员信息
     * @param form 商家端查看学员条件参数
     * @param token 商家登录token
     * @return
     */
    @ApiOperation("商家端条件查看学员信息")
    @PostMapping("/venueList.venue")
    public Result<List<VenueListUserDto>> venueListUser(@RequestBody VenueListUserForm form, @RequestHeader String token) {
        Integer venueId = MyJwtUtil.getVenueIdByKey(token, "venueId");
        List<VenueListUserDto> dtos = userInfoService.venueListUser(form,venueId);
        return Result.success("商家端查看学员信息成功",dtos);
    }
    /**
     * @param userId 用户id
     * @return
     */
    @ApiOperation("根据Id查看用户信息")
    @GetMapping("/findUserById")
    public Result<UserInfoDto> findUserById(Integer userId){
       UserInfoDto dtos =  userInfoService.findUserById(userId);
        return Result.success("根据Id查看用户信息",dtos);
    }

    /**
     * 用户修改密码
     * @param form 参数对象
     * @param token 用户登录token
     * @return
     */
    @ApiOperation("用户修改密码")
    @PostMapping("/updatePwd")
    public Result updatePwd(@RequestBody @Validated UpdateUserPwdForm form,@RequestHeader String token) {
        Integer userId = MyJwtUtil.getUserIdByKey(token, "userId");
        userInfoService.updatePwd(form,userId);
        return Result.success("用户修改密码成功");
    }

    /**
     *
     * @param phone 新手机号
     * @param token 用户登录的token
     * @return
     */
    @ApiOperation("用户修改手机号")
    @GetMapping("/updatePhone")
    public Result updatePwd(String phone,@RequestHeader String token){
        if (ObjectUtils.isEmpty(phone)) throw new ParameterValidException(500,"手机号不为空");
        String regex = "1[3-9]\\d{9}"; // 手机号码的正则表达式
        Matcher matcher = java.util.regex.Pattern.compile(regex).matcher(phone);
        if (!matcher.matches()) throw new ParameterValidException(500,"手机号格式有误");
        UserInfo user = userInfoService.getById(MyJwtUtil.getUserIdByKey(token, "userId"));
        UserInfo userInfo = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getUserPhone, phone));
        if (!ObjectUtils.isEmpty(userInfo) && !user.getUserPhone().equals(phone))  throw new UserInfoException(40007,"手机号已被注册");
        user.setUserPhone(phone);
        userInfoService.updateById(user);
        return Result.success("用户修改手机号成功");
    }

    /**
     * 管理端禁用用户
     * @param userId 用户id
     * @return
     */
    @ApiOperation("管理端禁用用户")
    @GetMapping("/disabled.api")
    public Result disabledUser(Integer userId){
        userInfoService.disabledUser(userId);
        return Result.success("禁用成功");
    }

    /**
     * 管理端启用用户
     * @param userId 用户id
     * @return
     */
    @ApiOperation("管理端启用用户")
    @GetMapping("/enable.api")
    public Result enableUser(Integer userId){
        userInfoService.enableUser(userId);
        return Result.success("启用成功");
    }

}

